﻿using System.Net.Http;
using AutoMapper;
using Common.Service;
using Common.Views;
using Core.Domain.Model;
using Dto.ApiRequests.MemberForms;
using NSBus.Dto.Commands;
using NServiceBus;
using Sanelib.Common.Extensions;
using Sanelib.Common.Helpers;
using Sanelib.DataView;
using Sanelib.Dto;
using Sanelib.Services.Impl;
using WebApp.Services;

namespace WebApp.ControllerApis
{
    public class AuthRecoveryController : SmartApiController
    {
        private readonly IViewRepository<MemberView> _memberViewRepository;
        private readonly ICryptographer _cryptographer;

        public IBus Bus { get; set; }

        public AuthRecoveryController(IUserSession userSession, IMappingEngine mappingEngine, IViewRepository<MemberView> memberViewRepository, ICryptographer cryptographer)
            : base(userSession, mappingEngine)
        {
            _memberViewRepository = memberViewRepository;
            _cryptographer = cryptographer;
        }

        public HttpResponseMessage Post(RecoverPasswordForm form)
        {
            var errors = new ErrorResult();

            if (string.IsNullOrEmpty(form.UserNameOrEmailAddress))
            {
                errors.AddError("UserName or EmailAddress", "Empty or Invalid");
                return Content(errors);
            }

            var property = form.UserNameOrEmailAddress.Contains("@")
                ? Property.Of<MemberView>(x => x.Email)
                : Property.Of<MemberView>(x => x.Code);

            var member = _memberViewRepository.GetByKey(property, form.UserNameOrEmailAddress);

            if (member == null)
            {
                errors.AddError("UserName or EmailAddress", "is not correct");
                return Content(errors);
            }

            Bus.Send<PasswordRecoveryTokenCommand>(c =>
            {
                c.UserId = member.Id;
                c.Url = GetPasswordRecoveryUrl();
            });

            var response = new WebApiResultResponse
            {
                IsSuccess = true,
                Message = "Your request has been received. Please check your mail."
            };

            return Content(response);
        }

        public HttpResponseMessage Put(ResetPasswordForm form)
        {
            var validator = new ErrorResult();

            if (form.Token != null || form.NewPassword != null || form.ConfirmPassword != null)
            {
                if (!form.Token.IsNotEmpty())
                    validator.AddError("Token", "is empty.");
                else if (form.Token.IsNotEmpty())
                {
                    var encryptToken = _cryptographer.ComputeHash(form.Token);
                    var member = _memberViewRepository.GetByKey(Property.Of<Member>(x => x.PasswordRetrievalToken), encryptToken);

                    if (member == null)
                        validator.AddError("Token", "is not valid");
                    else
                    {
                        if (!form.NewPassword.IsNotEmpty() || !form.ConfirmPassword.IsNotEmpty())
                            validator.AddError("NewPassword and ConfirmPassword", "are Required.");
                        else if (form.NewPassword != null && form.NewPassword.Length < 8)
                            validator.AddError("NewPassword", "Must be 8 characters long");
                        else if (!Formatter.HasAtLeast1Lowercase(form.NewPassword))
                            validator.AddError("NewPassword", "Must contains at least one LowerCase letter");
                        else if (!Formatter.HasAtLeast1Number(form.NewPassword))
                            validator.AddError("NewPassword", "Must contains at least one Number");
                        else if (!Formatter.HasAtLeast1SpecialChar(form.NewPassword))
                            validator.AddError("NewPassword", "Must contains at least one Special Character from  : _ # $ % ");
                        else if (!Formatter.HasAtLeast1Uppercase(form.NewPassword))
                            validator.AddError("NewPassword", "Must contains at least one UpperCase letter");
                        else if (form.NewPassword != form.ConfirmPassword)
                            validator.AddError("Newpassword and confirmpassword", "are not same.");
                        else
                        {
                            Bus.Send<ResetPasswordCommand>(c =>
                            {
                                c.Token = form.Token;
                                c.NewPassword = form.NewPassword;
                                c.ConfirmPassword = form.ConfirmPassword;
                            });

                            var response = new WebApiResultResponse { IsSuccess = true };
                            return Content(response);
                        }
                    }
                }
            }
            validator.AddError("Token or NewPassword or ConfirmPassword", "is Empty or Invalid");
            return Content(validator);
        }

        private string GetPasswordRecoveryUrl()
        {
            var generalConfig = ConfigProvider.GetGeneralConfig();
            var uri = generalConfig.ApplicationBaseUrl;
            return string.Format("{0}{1}", uri, Url.Route("Default", new { controller = "Auth", action = "Index" }));
        }
    }
}